<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Layout Class
 *
 * This class allows you to use CakePHP-like layouts stored in the
 * APPPATH/layouts folder to wrap around the application content
 *
 * Autoload this class, and use from your controllers as follows:
 * @example $this->layout->view('view_name', $data);
 *
 * @author Casey McLaughlin
 * @package CIHeadStart
 * @link http://code.google.com/p/ciheadstart
 */

// --------------------------------------------------------------------

/**
 * Set a notice
 *
 * Built-in helper function for the layout library
 * that sets a notice.
 *
 * @param string $message
 * @param string $type
 */
function set_notice($message, $type = 'normal')
{
	$ci =& get_instance();
	$ci->load->library('layout');
	$ci->layout->set_notice($message, $type);
}

// --------------------------------------------------------------------

/**
 * Check if there are any notices set
 *
 * @return boolean
 */
function there_are_notices()
{
	$ci =& get_instance();
	$ci->load->library('layout');
	
	if (count($ci->layout->get_notices()) > 0)
		return TRUE;
	else
		return FALSE;
}

// --------------------------------------------------------------------

class Layout
{
	var $obj;
	var $layout;
	var $load_head_items;
	var $notices;

	// --------------------------------------------------------------------

	/**
	 * Constructor
	 *
	 * @param string $layout
	 */
	function Layout($layout = "xhtml_main")
	{
		$this->obj =& get_instance();
		$this->set_layout($layout);

		$this->obj->load->library('session');
		if ($this->obj->session->userdata('layout_notices') && strlen($this->obj->session->userdata('layout_notices')) > 0)
		{
			$this->notices = unserialize($this->obj->session->userdata('layout_notices'));
			$this->obj->session->unset_userdata('layout_notices');
		}
		else
			$this->notices = array();

	}

	// --------------------------------------------------------------------

	/**
	 * Sets which layout file to use in the APPPATH/layouts folder
	 *
	 * If the layout file does not exist in the layouts folder,
	 * this method throw an Exception
	 *
	 * @param string $layout
	 */
	function set_layout($layout)
	{
		//layouts will always be relative to the 'views' folder
		if (is_readable(APPPATH . '/views/' . $layout . '.php'))
			$this->layout = $layout;
		elseif (is_readable(APPPATH . '/layouts/' . $layout . '.php'))
			$this->layout = '../layouts/' . $layout;
		else
			throw new Exception("Could not find the requested layout file in 'views' or 'layouts' folder: $layout");
	}

	// --------------------------------------------------------------------

	/**
	 * Adds an item to be placed before the </head> tag in an HTML
	 * file.
	 *
	 * These items will be added to the output only if there is a
	 * </head> tag present
	 *
	 * @param string $html_to_add
	 * @param string $position 'top' or 'bottom' or NULL (if it doesn't matter)
	 */
	function add_header_item($html_to_add, $position = NULL)
	{
		if ($position == 'top')
			array_unshift($this->load_head_items, $html_to_add);
		elseif ($position == 'bottom')
			array_push($this->load_head_items, $html_to_add);
		else
			$this->load_head_items[] = $html_to_add;
	}

	// --------------------------------------------------------------------

	function get_header_items()
	{
		return $this->load_head_items;
	}

	// --------------------------------------------------------------------

	function set_notice($message, $type = 'normal')
	{
		$notice = (object) NULL;
		$notice->message = $message;
		$notice->type = $type;

		$this->notices[] = $notice;

		$this->obj->session->set_userdata('layout_notices', serialize($this->notices));
	}

	// --------------------------------------------------------------------

	function get_notices($messages_only = FALSE)
	{
		if ($messages_only)
		{
			$out = array();
			foreach($this->notices as $notice)
				$out[] = $notice->message;
			return $out;
		}
		else
			return $this->notices;
	}

	// --------------------------------------------------------------------

	function get_notices_html($custom_class = NULL, $always_print_container = NULL)
	{
		if ($custom_class !== NULL)
			$custom_class = ' ' . $custom_class;

		if ($this->get_notices() > 0)
		{
			$html_out = '';

			foreach($this->get_notices() as $notice)
				$html_out .= "<p class='notice $notice->type'>$notice->message</p>";

			return "<div class='notices{$custom_class}'>$html_out</div>";
		}
		elseif ($always_print_container)
		{
			return "<div class='notices{$custom_class}'>&nbsp;</div>";
		}
		else
			return '';
	}

	// --------------------------------------------------------------------

  /**
	 * Load the view using the layout
	 *
	 * This function behaves exactly like the built-in CodeIgniter method load->view();
	 * @link http://codeigniter.com/user_guide/general/views.html
	 *
	 * The difference is that it wraps the view inside the desired layout file
	 * specified by the set_layout method in this class
	 * @see set_layout()
	 * 
	 * @param string $view
	 * @param array $data
	 * @param boolean $return
	 * @return string|void
	 */
	function view($view, $data = NULL, $return = FALSE)
	{
		$data['content_for_layout'] = $this->obj->load->view($view, $data, TRUE);
		$data['notices'] = $this->get_notices_html();

		if ($this->obj->session->userdata('layout_notices') && strlen($this->obj->session->userdata('layout_notices')) > 0)
			$this->obj->session->unset_userdata('layout_notices');

		$output = $this->obj->load->view($this->layout, $data, TRUE);

		if (isset($this->load_head_items) && is_array($this->load_head_items) && count($this->load_head_items) > 0 && strpos($output, '</head>') !== FALSE)
			$output = str_ireplace_limited('</head>', "\n<!-- Added by CI Layout Header Library -->\n" . implode('\n', $this->load_head_items) . '</head>', $output, 1);

		//Overriding stuff in the system/libraries/Loader.php -> _ci_load() function
		//If we start to get output errors, then we know to just change this back to:
		//$this->obj->load->view($this->layout, $data, FALSE
		ob_start();

		if ((bool) @ini_get('short_open_tag') === FALSE AND $this->obj->config->item('rewrite_short_tags') == TRUE)
			echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', $output)));
		else
			echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>",$output));

		log_message('debug', 'File loaded: '. APPPATH . 'views/' . $view);

		if($return)
		{
			$buffer = ob_get_contents();
			@ob_end_clean();
			return $output;
		}
		else
		{
			global $OUT;
			$OUT->append_output(ob_get_contents());
			@ob_end_clean();
		}
	}
}

/* End of file Layout.php */
/* Location: ./app/libraries/Layout.php */